import datetime
from decimal import Decimal
from typing import List

from module_admin.dao.cms_car_dao import CmsCarDao
from module_admin.dao.cms_driver_dao import CmsDriverDao
from module_admin.dao.cms_expenses_dao import CmsExpenseDao
from module_admin.dao.cms_order_bill_dao import CmsOrderBillDao
from module_admin.dao.cms_order_dao import CmsOrderDao
from module_admin.dao.cms_order_dispatch_dao import CmsOrderDispatchDao
from module_admin.dao.cms_order_execute_dao import CmsOrderExecuteDao
from module_admin.entity.do.cms_car import CmsCar
from module_admin.entity.do.cms_order import CmsOrder
from module_admin.dao.dept_dao import *
from module_admin.entity.do.cms_order_dispatch import CmsOrderDispatch
from module_admin.entity.do.cms_order_execute import CmsOrderExecute
from module_admin.entity.vo.cms_order_bill_vo import OrderBillModel
from module_admin.entity.vo.cms_order_dispatch_vo import OrderDispatchModelForCreate, OrderModelForDispatchDriver, \
    OrderDetailsForDriver, OrderDispatchModel, OrderDetailsForDriverQuery, ConfirmModel, OperateModel
from module_admin.entity.vo.cms_order_execute_vo import OrderExecuteModel
from module_admin.entity.vo.cms_order_vo import OrderModel, OrderModelForDispatchUrgent, CrudOrderResponse
from module_admin.entity.vo.expense_vo import ExpensesModelForJisuan
from module_admin.entity.vo.user_vo import CasdoorUser
from module_admin.enum.state_enum import OrderStateEnum, OrderApproveStateEnum, OrderDispatchStateEnum
from module_admin.service.cms_driver_service import CmsDriverService
from module_admin.service.cms_order_service import CmsOrderService
from module_admin.service.expenses_service import ExpensesService
from utils.log_util import *
from utils.stringUtils import stringUtils
from utils.uuid import UUID


class CmsOrderDispatchService:

    @classmethod
    def dispatch(cls, db: Session, request: OrderDispatchModelForCreate, current_user: CasdoorUser):
        #
        order_by_id: CmsOrder = CmsOrderDao.get_order_by_id(db, request.id)
        if order_by_id is None:
            return
        if order_by_id.state != OrderStateEnum.ddd.value:
            return
        for e in request.driver_and_car:
            car: CmsCar = CmsCarDao.get_car_by_id(db, int(e.car_id))
            if car is None:
                raise ValueError(f"车辆{e.car_id}不存在")
            expenses = CmsExpenseDao.get_one_by_car_type(db, car.car_type, car.car_brand)
            if expenses is None:
                raise ValueError(
                    f"车牌号为{car.car_number}的车辆,车型为{car.car_type},车辆品牌为{car.car_brand}未设置价格类型不能派车不存在")
        # 删除
        CmsOrderDispatchDao.delete_one_by_order_id(db, str(order_by_id.id))
        # 新增
        for e in request.driver_and_car:
            cms_order_dispatch = CmsOrderDispatch()
            cms_order_dispatch.id = int(UUID().uuid())
            cms_order_dispatch.order_id = order_by_id.order_id
            cms_order_dispatch.car_id = e.car_id
            cms_order_dispatch.driver_id = e.driver_id
            cms_order_dispatch.state = OrderDispatchStateEnum.not_confirm.value
            cms_order_dispatch.create_by = current_user.name
            cms_order_dispatch.update_by = current_user.name
            CmsOrderDispatchDao.create_order_dispatch(db, cms_order_dispatch)
            CmsOrderDao.update_state(db, request.id, OrderStateEnum.dqr.value)

    @classmethod
    def driver_operate(cls, db: Session, request: OrderModelForDispatchDriver, current_user: CasdoorUser):
        try:
            # 根据司机登录账号获取driver_id
            driver_id = ""
            # refuse(退回) confirm(确认) start(开始任务) end(完结)
            order_by_id: CmsOrder = CmsOrderDao.get_order_by_id(db, request.id)
            order_dispatch: CmsOrderDispatch = (CmsOrderDispatchDao
                                                .get_one_by_order_id(db, order_by_id.order_id))
            if order_by_id is None or request.operate is None:
                return
            order_update_state: int = 0
            order_dispatch_update_state: int = 0
            refuse_reason = None
            confirm_time = None
            if request.operate == "refuse" and order_by_id.state == OrderStateEnum.dqr.value:
                order_update_state = OrderStateEnum.ddd.value
                order_dispatch_update_state = OrderDispatchStateEnum.refuse.value
                refuse_reason = request.reason
            elif request.operate == "confirm" and order_by_id.state == OrderStateEnum.dqr.value:
                order_update_state = OrderStateEnum.dks.value
                order_dispatch_update_state = OrderDispatchStateEnum.confirm.value
                confirm_time = datetime.datetime.now()
            elif request.operate == "start" and order_by_id.state == OrderStateEnum.dks.value:
                # if CmsDriverService.have_jxz(db,)
                # 生成任务开始
                order_update_state = OrderStateEnum.jxz.value
                order_execute_model = OrderExecuteModel()
                order_execute_model.id = int(UUID().uuid())
                order_execute_model.state = 1
                order_execute_model.order_id = order_by_id.order_id
                order_execute_model.car_id = order_dispatch.car_id
                order_execute_model.driver_id = order_dispatch.driver_id
                order_execute_model.rading_count = order_by_id.rading_count
                order_execute_model.reality_begin_time = datetime.datetime.now()
                order_execute_model.start_mileage = request.start_mileage
                order_execute_model.start_file = request.start_file
                order_execute_model.bill_type = request.bill_type
                order_execute_model.create_by = current_user.name
                order_execute_model.update_by = current_user.name
                CmsOrderExecuteDao.create_order_execute(db, order_execute_model)
            elif request.operate == "end" and order_by_id.state == OrderStateEnum.jxz.value:
                # 生成任务结果
                order_execute: CmsOrderExecute = CmsOrderExecuteDao.get_one_by_order_id(db, order_by_id.order_id)
                order_execute.reality_end_time = datetime.datetime.now()
                order_execute.end_mileage = request.end_mileage
                if order_execute.start_mileage and request.end_mileage:
                    order_execute.sheet_mileage = Decimal(request.end_mileage) - Decimal(order_execute.start_mileage)
                order_execute.end_file = request.end_file
                order_execute.sign = request.sign
                model = OrderExecuteModel(**order_execute.__dict__)
                order_execute_update_dict = model.dict(exclude_unset=True)
                CmsOrderExecuteDao.update_order_execute_by_id(db, order_execute_update_dict)
                # 生成费用
                get_expenses: List[ExpensesModelForJisuan] = ExpensesService.get_expenses(db, order_by_id.order_id)
                starting_expenses = Decimal("0")
                day_expenses = Decimal("0")
                suspended_expenses = Decimal("0") + (
                    Decimal(request.suspended_expenses) if request.suspended_expenses else Decimal("0"))
                expenses = Decimal("0")
                if get_expenses:
                    for e in get_expenses:
                        starting_expenses = starting_expenses + (
                            e.starting_price_sum if e.starting_price_sum else Decimal("0"))
                        day_expenses = day_expenses + (e.day_price_sum if e.day_price_sum else Decimal("0"))
                        expenses = expenses + (e.miles_price_sum if e.miles_price_sum else Decimal("0"))
                # 生成任务账单
                order_bill = OrderBillModel()
                order_bill.id = int(UUID().uuid())
                order_bill.state = "未结算"
                order_bill.order_id = order_by_id.order_id
                order_bill.car_id = order_dispatch.car_id
                order_bill.driver_id = order_dispatch.driver_id
                order_bill.bill_type = order_execute.bill_type
                order_bill.system_mileage = Decimal("0")
                order_bill.sheet_mileage = order_execute.sheet_mileage
                if order_execute.bill_type == "beidou":
                    order_bill.expenses = expenses
                else:
                    order_bill.sheet_expenses = expenses
                order_bill.starting_expenses = starting_expenses
                order_bill.day_expenses = day_expenses
                order_bill.suspended_expenses = suspended_expenses
                order_bill.sum_expenses = starting_expenses + day_expenses + suspended_expenses + expenses
                order_bill.create_by = current_user.name
                order_bill.update_by = current_user.name
                if order_execute.start_mileage and request.end_mileage:
                    order_bill.sheet_mileage = Decimal(request.end_mileage) - Decimal(order_execute.start_mileage)
                CmsOrderBillDao.create_order_bill(db, order_bill)
                order_update_state = OrderStateEnum.ywj.value
            if order_update_state != 0:
                CmsOrderDao.update_state(db, request.id, order_update_state)
            if order_dispatch_update_state != 0:
                CmsOrderDispatchDao.update_state_reason(db, order_by_id.order_id, driver_id,
                                                        order_dispatch_update_state,
                                                        refuse_reason, confirm_time)
        except Exception as e:
            db.rollback()
            logger.exception(e)
            raise ValueError(e)

    @classmethod
    def detail(cls, db: Session, query: OrderDetailsForDriverQuery):
        # 用车信息#
        driver_confirm: OrderDetailsForDriver = OrderDetailsForDriver()
        by_id: CmsOrder = CmsOrderDao.get_order_by_id(db, query.id)
        order_model = OrderModel(**vars(by_id))
        driver_confirm.order_details = order_model
        # 用车人-单个
        # 用车部门-单个
        if by_id is not None:
            order_execute = CmsOrderExecuteDao.get_one_by_order_id(db, by_id.order_id)
            # 确认信息
            confirm_model = ConfirmModel()
            confirm_model.order_state = by_id.state
            driver_confirm.confirm_details = confirm_model
            # 操作信息
            operate_model = OperateModel()
            operate_model.order_state = by_id.state
            if order_execute is not None:
                operate_model.confirm_time = order_execute.create_time
                driver = CmsDriverDao.get_one_by_driver_id(db, order_execute.driver_id)
                if driver is not None:
                    operate_model.driver_name = driver.driver_name
            driver_confirm.operate_details = operate_model
        return driver_confirm

    @classmethod
    def dispatch_urgent(cls, db: Session, order_request: OrderModelForDispatchUrgent, current_user: CasdoorUser):
        try:
            # order
            order_model = OrderModel(**order_request.dict())
            destination = stringUtils.get_one(order_model.destination_list)
            # 待调度
            order_model.state = OrderStateEnum.dqr.value
            order_model.order_id = "ord_" + UUID().uuid()
            order_model_result = CmsOrderDao.create_order(db, order_model, destination)
            # orderDispatch新增
            cms_order_dispatch = CmsOrderDispatch()
            cms_order_dispatch.id = int(UUID().uuid())
            cms_order_dispatch.order_id = order_model_result.execute_id
            cms_order_dispatch.car_id = order_request.car_id
            cms_order_dispatch.driver_id = order_request.driver_id
            cms_order_dispatch.state = OrderDispatchStateEnum.confirm.value
            cms_order_dispatch.create_by = current_user.name
            cms_order_dispatch.update_by = current_user.name
            CmsOrderDispatchDao.create_order_dispatch(db, cms_order_dispatch)
            result = dict(is_success=True, message="")
        except Exception as e:
            db.rollback()
            result = dict(is_success=False, message=str(e))
        return CrudOrderResponse(**result)

    @classmethod
    def cancel(cls, db, order_id):
        order: CmsOrder = CmsOrderDao.get_order_by_id(db, order_id)
        if order is None:
            raise ValueError("该用车申请不存在")
        if not OrderStateEnum.can_cancel(order.state):
            raise ValueError("该用车申请状态是" + OrderStateEnum.get_state_name(order.state) + "不能取消")
        CmsOrderDao.update_state(db, order_id, OrderStateEnum.yqx.value)
